"""浏览器驱动管理工具"""

import os
import platform
import shutil
import subprocess
import sys
import time
from pathlib import Path
from typing import Dict, Optional, Tuple, List

from rpa_framework.rpa_logging.logger import get_logger

logger = get_logger("rpa.utils.browser_driver_manager")


class BrowserDriverManager:
    """浏览器驱动管理器"""
    
    # 支持的浏览器类型
    SUPPORTED_BROWSERS = ["chrome", "firefox", "edge"]
    
    # 驱动下载URL模板
    DRIVER_URLS = {
        "chrome": "https://chromedriver.chromium.org/downloads",
        "firefox": "https://github.com/mozilla/geckodriver/releases",
        "edge": "https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/"
    }
    
    def __init__(self, driver_dir: Optional[str] = None):
        """初始化浏览器驱动管理器
        
        Args:
            driver_dir: 驱动存储目录，默认为当前目录下的drivers文件夹
        """
        # 设置驱动目录
        if driver_dir:
            self.driver_dir = Path(driver_dir)
        else:
            self.driver_dir = Path(os.getcwd()) / "drivers"
        
        # 确保驱动目录存在
        self.driver_dir.mkdir(exist_ok=True)
        
        # 获取当前操作系统
        self.os = platform.system().lower()  # Windows, Darwin(macOS), Linux
        self.architecture = platform.architecture()[0]  # 32bit or 64bit
    
    def get_driver_path(self, browser_type: str) -> Optional[str]:
        """获取浏览器驱动路径
        
        Args:
            browser_type: 浏览器类型 (chrome, firefox, edge)
            
        Returns:
            驱动文件路径，如果不存在返回None
        """
        if browser_type not in self.SUPPORTED_BROWSERS:
            logger.error(f"不支持的浏览器类型: {browser_type}")
            return None
        
        # 根据浏览器类型和操作系统确定驱动文件名
        driver_names = {
            "chrome": "chromedriver",
            "firefox": "geckodriver",
            "edge": "msedgedriver"
        }
        
        # Windows系统添加.exe后缀
        if self.os == "windows":
            driver_name = f"{driver_names[browser_type]}.exe"
        else:
            driver_name = driver_names[browser_type]
        
        driver_path = self.driver_dir / driver_name
        
        if driver_path.exists() and os.access(str(driver_path), os.X_OK):
            logger.debug(f"找到驱动文件: {driver_path}")
            return str(driver_path)
        
        logger.debug(f"未找到驱动文件: {driver_path}")
        return None
    
    def check_driver_exists(self, browser_type: str) -> bool:
        """检查驱动是否存在
        
        Args:
            browser_type: 浏览器类型
            
        Returns:
            驱动是否存在
        """
        return self.get_driver_path(browser_type) is not None
    
    def check_driver_version(self, browser_type: str) -> Optional[str]:
        """检查驱动版本
        
        Args:
            browser_type: 浏览器类型
            
        Returns:
            驱动版本信息，如果无法获取返回None
        """
        driver_path = self.get_driver_path(browser_type)
        if not driver_path:
            return None
        
        try:
            # 尝试通过命令行获取版本信息
            if browser_type == "chrome":
                result = subprocess.run(
                    [driver_path, "--version"], 
                    stdout=subprocess.PIPE, 
                    stderr=subprocess.PIPE,
                    text=True
                )
                if result.returncode == 0:
                    return result.stdout.strip()
            elif browser_type == "firefox":
                result = subprocess.run(
                    [driver_path, "--version"], 
                    stdout=subprocess.PIPE, 
                    stderr=subprocess.PIPE,
                    text=True
                )
                if result.returncode == 0:
                    return result.stdout.strip()
            elif browser_type == "edge":
                result = subprocess.run(
                    [driver_path, "--version"], 
                    stdout=subprocess.PIPE, 
                    stderr=subprocess.PIPE,
                    text=True
                )
                if result.returncode == 0:
                    return result.stdout.strip()
            
        except Exception as e:
            logger.error(f"获取驱动版本失败: {e}")
        
        return None
    
    def download_driver(self, browser_type: str) -> bool:
        """下载浏览器驱动
        
        Args:
            browser_type: 浏览器类型
            
        Returns:
            是否下载成功
        """
        if browser_type not in self.SUPPORTED_BROWSERS:
            logger.error(f"不支持的浏览器类型: {browser_type}")
            return False
        
        # 首先检查驱动是否已经存在
        existing_driver = self.get_driver_path(browser_type)
        if existing_driver:
            logger.info(f"驱动已存在: {existing_driver}")
            return True
        
        try:
            # 检查webdriver_manager是否安装
            try:
                import webdriver_manager
                logger.debug("webdriver_manager 已安装")
            except ImportError:
                logger.info("正在安装 webdriver_manager...")
                subprocess.check_call([sys.executable, "-m", "pip", "install", "webdriver-manager"])
            
            # 记录开始下载的信息
            logger.info(f"开始下载{self._get_browser_name(browser_type)}驱动...")
            
            # 根据浏览器类型使用相应的管理器下载驱动
            # 尝试使用不同的参数名来适配不同版本的webdriver-manager
            try:
                if browser_type == "chrome":
                    from webdriver_manager.chrome import ChromeDriverManager
                    # 尝试使用path参数（旧版本）
                    try:
                        driver_path = ChromeDriverManager(path=str(self.driver_dir)).install()
                    except TypeError:
                        # 如果失败，尝试使用cache_dir参数（新版本）
                        try:
                            driver_path = ChromeDriverManager(cache_dir=str(self.driver_dir)).install()
                        except TypeError:
                            # 最新版本可能完全改变了API，使用默认方式
                            driver_path = ChromeDriverManager().install()
                elif browser_type == "firefox":
                    from webdriver_manager.firefox import GeckoDriverManager
                    # 尝试使用path参数（旧版本）
                    try:
                        driver_path = GeckoDriverManager(path=str(self.driver_dir)).install()
                    except TypeError:
                        # 如果失败，尝试不带参数
                        driver_path = GeckoDriverManager().install()
                elif browser_type == "edge":
                    from webdriver_manager.microsoft import EdgeChromiumDriverManager
                    # 尝试使用path参数（旧版本）
                    try:
                        driver_path = EdgeChromiumDriverManager(path=str(self.driver_dir)).install()
                    except TypeError:
                        # 如果失败，尝试使用cache_dir参数（新版本）
                        try:
                            driver_path = EdgeChromiumDriverManager(cache_dir=str(self.driver_dir)).install()
                        except TypeError:
                            # 最新版本可能完全改变了API，使用默认方式
                            driver_path = EdgeChromiumDriverManager().install()
            except Exception as e:
                # 如果所有尝试都失败，使用默认安装方式，然后复制到指定目录
                logger.warning(f"使用默认参数下载驱动: {str(e)}")
                if browser_type == "chrome":
                    from webdriver_manager.chrome import ChromeDriverManager
                    default_path = ChromeDriverManager().install()
                elif browser_type == "firefox":
                    from webdriver_manager.firefox import GeckoDriverManager
                    default_path = GeckoDriverManager().install()
                elif browser_type == "edge":
                    from webdriver_manager.microsoft import EdgeChromiumDriverManager
                    default_path = EdgeChromiumDriverManager().install()
                
                # 复制驱动文件到指定目录
                import shutil
                driver_name = os.path.basename(default_path)
                target_path = str(self.driver_dir / driver_name)
                shutil.copy2(default_path, target_path)
                driver_path = target_path
                logger.info(f"已将驱动从默认位置复制到: {driver_path}")
            
            # 检查驱动是否在指定目录中，如果不是则复制过去
            import shutil  # 确保在当前作用域中导入shutil
            if not str(driver_path).startswith(str(self.driver_dir)):
                driver_name = os.path.basename(driver_path)
                target_path = str(self.driver_dir / driver_name)
                try:
                    shutil.copy2(driver_path, target_path)
                    logger.info(f"驱动已成功安装到指定目录: {target_path}")
                    driver_path = target_path
                except Exception as copy_error:
                    logger.warning(f"驱动下载成功但复制到指定目录失败: {copy_error}")
                    logger.info(f"驱动可在临时位置使用: {driver_path}")
            else:
                logger.info(f"驱动已成功安装到指定目录: {driver_path}")
            
            return True
            
        except Exception as e:
            error_msg = str(e)
            if "Could not reach host" in error_msg or "offline" in error_msg.lower():
                logger.warning(f"网络连接问题，无法下载{self._get_browser_name(browser_type)}驱动: {error_msg}")
                logger.warning(f"请检查网络连接，或手动下载驱动并放到目录: {self.driver_dir}")
            else:
                logger.error(f"下载驱动失败: {error_msg}")
            return False
    
    def _get_browser_name(self, browser_type: str) -> str:
        """获取浏览器的中文名称
        
        Args:
            browser_type: 浏览器类型
            
        Returns:
            浏览器中文名称
        """
        browser_names = {
            "chrome": "Chrome",
            "firefox": "Firefox",
            "edge": "Edge"
        }
        return browser_names.get(browser_type, browser_type)
    
    def update_driver(self, browser_type: str) -> bool:
        """更新浏览器驱动
        
        Args:
            browser_type: 浏览器类型
            
        Returns:
            是否更新成功
        """
        # 先尝试删除旧驱动
        driver_path = self.get_driver_path(browser_type)
        if driver_path:
            try:
                os.remove(driver_path)
                logger.debug(f"已删除旧驱动: {driver_path}")
            except Exception as e:
                logger.error(f"删除旧驱动失败: {e}")
        
        # 下载新驱动
        return self.download_driver(browser_type)
    
    def list_installed_drivers(self) -> Dict[str, Dict[str, str]]:
        """列出所有已安装的驱动
        
        Returns:
            驱动信息字典，格式: {浏览器类型: {"path": 路径, "version": 版本}}
        """
        drivers_info = {}
        
        for browser in self.SUPPORTED_BROWSERS:
            path = self.get_driver_path(browser)
            if path:
                version = self.check_driver_version(browser) or "未知"
                drivers_info[browser] = {
                    "path": path,
                    "version": version
                }
        
        return drivers_info
    
    def remove_driver(self, browser_type: str) -> bool:
        """删除浏览器驱动
        
        Args:
            browser_type: 浏览器类型
            
        Returns:
            是否删除成功
        """
        driver_path = self.get_driver_path(browser_type)
        if not driver_path:
            logger.warning(f"驱动不存在: {browser_type}")
            return False
        
        try:
            os.remove(driver_path)
            logger.info(f"已删除驱动: {driver_path}")
            return True
        except Exception as e:
            logger.error(f"删除驱动失败: {e}")
            return False
    
    def get_browser_info(self) -> List[Dict[str, str]]:
        """获取浏览器信息
        
        Returns:
            浏览器信息列表
        """
        browsers_info = []
        
        # 检查Chrome
        chrome_path = self._find_chrome()
        browsers_info.append({
            "type": "chrome",
            "name": "Google Chrome",
            "path": chrome_path,
            "installed": chrome_path is not None,
            "driver_installed": self.check_driver_exists("chrome"),
            "driver_download_url": self.DRIVER_URLS["chrome"]
        })
        
        # 检查Firefox
        firefox_path = self._find_firefox()
        browsers_info.append({
            "type": "firefox",
            "name": "Mozilla Firefox",
            "path": firefox_path,
            "installed": firefox_path is not None,
            "driver_installed": self.check_driver_exists("firefox"),
            "driver_download_url": self.DRIVER_URLS["firefox"]
        })
        
        # 检查Edge
        edge_path = self._find_edge()
        browsers_info.append({
            "type": "edge",
            "name": "Microsoft Edge",
            "path": edge_path,
            "installed": edge_path is not None,
            "driver_installed": self.check_driver_exists("edge"),
            "driver_download_url": self.DRIVER_URLS["edge"]
        })
        
        return browsers_info
    
    def _find_chrome(self) -> Optional[str]:
        """查找Chrome浏览器路径"""
        if self.os == "windows":
            # Windows系统查找Chrome
            paths = [
                "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
                "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"
            ]
            for path in paths:
                if os.path.exists(path):
                    return path
        elif self.os == "darwin":  # macOS
            path = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
            if os.path.exists(path):
                return path
        elif self.os == "linux":
            # Linux系统查找Chrome
            for path in ["/usr/bin/google-chrome", "/usr/bin/google-chrome-stable"]:
                if os.path.exists(path):
                    return path
        
        return None
    
    def _find_firefox(self) -> Optional[str]:
        """查找Firefox浏览器路径"""
        if self.os == "windows":
            # Windows系统查找Firefox
            paths = [
                "C:\\Program Files\\Mozilla Firefox\\firefox.exe",
                "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"
            ]
            for path in paths:
                if os.path.exists(path):
                    return path
        elif self.os == "darwin":  # macOS
            path = "/Applications/Firefox.app/Contents/MacOS/firefox"
            if os.path.exists(path):
                return path
        elif self.os == "linux":
            # Linux系统查找Firefox
            path = "/usr/bin/firefox"
            if os.path.exists(path):
                return path
        
        return None
    
    def _find_edge(self) -> Optional[str]:
        """查找Edge浏览器路径"""
        if self.os == "windows":
            # Windows系统查找Edge
            paths = [
                "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
                "C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe"
            ]
            for path in paths:
                if os.path.exists(path):
                    return path
        elif self.os == "darwin":  # macOS
            path = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
            if os.path.exists(path):
                return path
        elif self.os == "linux":
            # Linux系统查找Edge
            path = "/usr/bin/microsoft-edge"
            if os.path.exists(path):
                return path
        
        return None


if __name__ == "__main__":
    # 示例用法
    manager = BrowserDriverManager()
    
    # 列出浏览器信息
    print("浏览器信息:")
    for browser in manager.get_browser_info():
        print(f"- {browser['name']}: {'已安装' if browser['installed'] else '未安装'}")
        print(f"  驱动状态: {'已安装' if browser['driver_installed'] else '未安装'}")
    
    # 尝试下载Chrome驱动
    if not manager.check_driver_exists("chrome"):
        print("\n正在下载Chrome驱动...")
        success = manager.download_driver("chrome")
        print(f"下载结果: {'成功' if success else '失败'}")
    
    # 列出已安装的驱动
    print("\n已安装的驱动:")
    for browser, info in manager.list_installed_drivers().items():
        print(f"- {browser}: {info['version']}")
        print(f"  路径: {info['path']}")